<template>
  <section class="MapBlock">
    <div class="searchBlock" id="searchBlock">
      <el-select
        v-model="searchVal"
        placeholder="请输入关键字"
        style="width: 260px"
        remote
        :remote-method="handleSearch"
        filterable
        no-data-text="无数据"
        @change="handleChange"
      >
        <el-option
          v-for="(item, index) in searchData"
          :key="index"
          :label="item.title"
          :value="index"
        >
          {{ item.title }}
        </el-option>
      </el-select>
    </div>
    <div id="container" style="width: 100%; height: 420px"></div>
  </section>
</template>
<script>
import axios from "axios";
import { mapKey } from "@/utils/map/mapKey.js";
export default {
  name: "Map",
  props: {
    // 禁止操作
    isInverseAnalysis: {
      type: Boolean,
      default: false,
    },
    dialogForm: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  data() {
    return {
      searchVal: undefined,
      searchData: [],
      map: null,
      marker: null,
      geocoder: null,
      cache: {
        timer: null,
        data: null,
      },
    };
  },
  watch: {
    dialogForm: {
      handler(val) {
        this.manualDestroy();
        this.$nextTick(() => {
          if (this.marker) {
            this.marker.setMap(null);
          }
          if (val.lat) {
            let { lat, lng } = val;
            this.addMarker({ lat, lng });
          }
        });
      },
      deep: true, //对象内部的属性监听，也叫深度监听
      immediate: true,
    },
  },
  mounted() {
    window.self = this;
    window.init = function () {
      var myLatlng = new qq.maps.LatLng(39.916527, 116.397128);
      var myOptions = {
        zoom: 13,
        center: myLatlng,
        mapTypeId: qq.maps.MapTypeId.ROADMAP,
      };
      self.map = new qq.maps.Map(
        document.getElementById("container"),
        myOptions
      );

      self.movePosition();
      self.bindingEvent();
    };
    this.loadScript();
  },
  methods: {
    manualDestroy() {
      clearInterval(this.cache.timer);
      if (this.marker) {
        this.marker.setMap(null);
      }
      if (this.map) {
        this.movePosition();
      }
      this.searchVal = undefined;
    },
    /**
     * [loadScript 异步加载依赖]
     * @return {[type]} [description]
     */
    loadScript() {
      var script = document.createElement("script");
      script.type = "text/javascript";
      // script.src = "https://map.qq.com/api/js?v=2.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77&callback=init";
      script.src = `https://map.qq.com/api/js?v=2.exp&key=${mapKey}&callback=init`;
      document.body.appendChild(script);
      // var script2 = document.createElement("script");
      // script2.type = "text/javascript";
      // script2.src = "https://map.qq.com/api/gljs?v=1.exp&libraries=service&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77"
      // document.body.appendChild(script2);
    },
    /**
     * [movePosition 移动地图中心点]
     * @param  {[type]} latLng [经度纬度]
     * @return {[type]}     [description]
     */
    movePosition(latLng) {
      if (!latLng) {
        latLng = {
          lat: 39.916527,
          lng: 116.397128,
        };
      }
      this.map.panTo(new qq.maps.LatLng(latLng.lat, latLng.lng));
    },
    /**
     * [bindingEvent 绑定地图事件]
     * @return {[type]} [description]
     */
    bindingEvent() {
      // 清空搜索下拉选中值
      this.searchVal = undefined;
      this.listener = qq.maps.event.addListener(
        this.map,
        "click",
        function (e) {
          // console.log('您点击了地图。', e);
          self.addMarker(e.latLng);
          if (self.isInverseAnalysis) {
            self.formSubmit(e);
          } else {
            self.$emit("click", e);
          }
        }
      );
    },
    /**
     * [addMarker 添加标志物]
     * @param {[type]} latLng [经纬度对象]
     */
    addMarker(latLng) {
      if (this.marker) {
        this.marker.setMap(null);
      }
      try {
        const location = new qq.maps.LatLng(latLng.lat, latLng.lng);
        this.marker = new qq.maps.Marker({
          position: location,
          map: this.map,
        });
        this.movePosition(latLng);
      } catch {
        // console.log('开始');
        clearInterval(this.cache.timer);
        this.cache.data = latLng;
        this.cache.timer = setInterval(() => {
          const location = new qq.maps.LatLng(
            this.cache.data.lat,
            this.cache.data.lng
          );
          if (location) {
            // console.log('结束');
            clearInterval(this.cache.timer);
            this.marker = new qq.maps.Marker({
              position: location,
              map: this.map,
            });
            this.movePosition(latLng);
          }
        }, 500);
      }
    },
    formSubmit(e) {
      const self = this;
      var url = "https://apis.map.qq.com/ws/geocoder/v1/";
      const config = {
        url: url,
        callback: "callback",
        time: 90000,
        data: {
          location: e.latLng.lat + "," + e.latLng.lng,
          key: mapKey,
          output: "jsonp",
        },
        success: function (res) {
          if (res.result && res.result.ad_info && res.result.ad_info.adcode) {
            e.result = res.result;
            e.address = res.result.address;
            self.$emit("click", e);
          } else {
            self.$message.error("地图服务请求错误！");
          }
        },
        fail: function () {
          self.$message.error("地图服务请求超时！");
        },
      };
      this.jsonp(config);
    },
    dropDownPosition() {
      return document.getElementById("searchBlock");
    },
    /**
     * [handleSearch 远程搜索]
     * @param  {[type]} e [搜索条件]
     * @return {[type]}   [description]
     */
    handleSearch(e) {
      //   console.log("远程搜索", e);
      this.searchVal = e;
      this.searchData = [];
      if (!this.searchVal) {
        return;
      }
      const self = this;
      var url = "https://apis.map.qq.com/ws/place/v1/suggestion";
      const config = {
        url: url,
        callback: "callback",
        time: 90000,
        data: {
          keyword: self.searchVal,
          key: mapKey,
          output: "jsonp",
        },
        success: function (res) {
          if (res.data) {
            self.searchData = res.data;
          }
        },
        fail: function () {
          self.$message.error("地图服务请求超时！");
        },
      };
      this.jsonp(config);
    },
    /**
     * [handleChange 选中项]
     * @param  {[type]} index [所在数组序号]
     * @return {[type]}       [description]
     */
    handleChange(index) {
      var e = {
        result: {
          ad_info: {},
        },
      };
      e.latLng = this.searchData[index].location;
      e.result.ad_info = this.searchData[index];
      e.address = this.searchData[index].address;
      //   console.log("选中项", e);

      this.addMarker(e.latLng);
      this.$emit("click", e);
    },
    jsonp(options) {
      options = options || {};
      if (!options.url || !options.callback) {
        throw new Error("参数不合法");
      }
      //创建 script 标签并加入到页面中
      var callbackName = ("jsonp" + Math.random()).replace(".", "");
      var oHead = document.getElementsByTagName("head")[0];
      options.data[options.callback] = callbackName;
      var params = this.formatParams(options.data);
      var oS = document.createElement("script");
      oHead.appendChild(oS);
      //创建jsonp回调函数
      window[callbackName] = function (json) {
        oHead.removeChild(oS);
        clearTimeout(oS.timer);
        window[callbackName] = null;
        options.success && options.success(json);
      };
      //发送请求
      oS.src = options.url + "?" + params;
      //超时处理
      if (options.time) {
        oS.timer = setTimeout(function () {
          window[callbackName] = null;
          oHead.removeChild(oS);
          options.fail && options.fail({ message: "请求超时！" });
        }, options.time);
      }
    },
    //格式化参数
    formatParams(data) {
      var arr = [];
      for (var name in data) {
        arr.push(
          encodeURIComponent(name) + "=" + encodeURIComponent(data[name])
        );
      }
      return arr.join("&");
    },
  },
  destroyed() {
    this.manualDestroy();
  },
};
</script>
<style scoped>
.MapBlock {
  position: relative;
}
.searchBlock {
  position: absolute;
  top: 4px;
  left: 70px;
  z-index: 1;
}
</style>
